package org.ysh.core.shiro;

import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.springframework.util.ObjectUtils;
import org.ysh.core.cache.Constants;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import static org.apache.shiro.web.util.WebUtils.getRequest;

@Slf4j
public class CustomeFormAuthenticationFilter extends FormAuthenticationFilter {

    public static String CAPTCHA_PARAM = "captcha";

    // 获取验证码
    public String getCaptcha(ServletRequest request) {
        return request.getParameter(CAPTCHA_PARAM);
    }

    // 重写createToken方法
    @Override
    protected CaptchaUsernamePasswordToken createToken(ServletRequest request, ServletResponse response) {
        String username = getUsername(request);
        String password = getPassword(request);
        String captcha = getCaptcha(request);
        boolean rememberMe = isRememberMe(request);
        String host = getHost(request);
        return new CaptchaUsernamePasswordToken(username, password, rememberMe, host, captcha);
    }

    // 重写登录流程
    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
        CaptchaUsernamePasswordToken token = createToken(request, response);
        if (token == null) {
            String msg = "createToken method implementation returned null. A valid non-null AuthenticationToken " +
                    "must be created in order to execute a login attempt.";
            throw new IllegalStateException(msg);
        }
        try {
            // 图形验证码校验
            doCaptchaValidate(token, request);

            // 登录
            getSubject(request, response).login(token);
            // 设置登录的用户到HttpSession中
            ((HttpServletRequest)request).getSession().setAttribute(Constants.CURRENT_USER, SecurityUtils.getSubject().getSession().getAttribute(Constants.CURRENT_USER));
            return onLoginSuccess(token, getSubject(request, response), request, response);
        } catch (AuthenticationException e) {
            return onLoginFailure(token, e, request, response);
        }
    }


    //重写setFailureAttribute方法，将异常存入request中，便于前端获取
    protected void setFailureAttribute(ServletRequest request, AuthenticationException ae) {
        request.setAttribute(this.getFailureKeyAttribute(), ae);
    }

    private void doCaptchaValidate(CaptchaUsernamePasswordToken token,
                                   ServletRequest request) {
        String captcha = token.getCaptcha();
        HttpServletRequest req = (HttpServletRequest) request;
        String attribute = (String) req.getSession().getAttribute(
                com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
        if (ObjectUtils.isEmpty(attribute)) {
            throw new ErrorCaptchaException("未获取到后台的图形验证码信息");
        }

        if (ObjectUtils.isEmpty(captcha)
                || !captcha.equalsIgnoreCase(attribute)) {
            throw new ErrorCaptchaException("图形验证码错误!");
        }
        req.getSession().removeAttribute(
                com.google.code.kaptcha.Constants.KAPTCHA_SESSION_KEY);
    }


}
